package com.ultron.common.util;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;

import javax.annotation.Nullable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static cn.hutool.core.text.CharSequenceUtil.lowerFirst;

/**
 * 常用的一些方法
 */
public class Func {
    /**
     * NumbersList转Long型List
     *
     * @param numbers
     * @return
     */
    public static <T> List<Long> toLongList(List<T> numbers) {
        return numbers.stream().map(Func::toLong).collect(Collectors.toList());
    }

    public static <T> Long toLong(T t) {
        try {
            return Long.parseLong(t.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0L;
    }

    public static boolean isEmpty(Object cache) {
        return Objects.isNull(cache);
    }

    public static <T> boolean isEmpty(List<T> cache) {
        return cache == null || cache.size() < 1;
    }

    public static boolean isEmpty(String str) {
        return Objects.isNull(str) || str.equals("");
    }

    public static boolean isEmpty(long[] cache) {
        return cache == null || cache.length < 1;
    }

    public static <T> boolean isEmpty(T[] array) {
        return array == null || array.length == 0;
    }

    public static <T> boolean isNotEmpty(List<T> list) {
        return list != null && list.size() > 0;
    }

    public static boolean isNotEmpty(Object o) {
        return o != null;
    }

    public static boolean isNotEmpty(String o) {
        return o != null && !o.equals("");
    }


    /**
     * 字符串转longlist
     *
     * @param ids
     * @return
     */
    public static List<Long> toLongList(String ids) {
        return toLongList(ids, ",");
    }

    public static List<Long> toLongList(String ids, String split) {
        String[] longs = ids.split(split);
        List<Long> list = new ArrayList<>();
        for (String l : longs) {
            list.add(Long.parseLong(l.trim()));
        }
        return list;
    }

    public static List<String> toList(String strs) {
        String[] strings = StrUtil.splitToArray(strs, ",");
        return Arrays.asList(strings);
    }

    /**
     * 获取雪花id。
     *
     * @return
     */
    public static long getSnowflake() {
        Snowflake snowflake = IdUtil.getSnowflake(1, 1);
        long id = snowflake.nextId();
        return id;
    }

    /**
     * 获取雪花id。
     *
     * @return
     */
    public static long getSnowflake(int workId, int datacenterId) {
        Snowflake snowflake = IdUtil.getSnowflake(workId, datacenterId);
        return snowflake.nextId();
    }

    /**
     * 通过方法得到字段名
     *
     * @param fn
     * @param <T>
     * @return
     */

    public static <T> String getFieldName(Function<T, ?> fn, Class<T> tClass) {
        // 从function取出序列化方法
        Method writeReplaceMethod = getMethod(fn);
        SerializedLambda serializedLambda = getSerializedLambda(writeReplaceMethod, fn);
        // 从lambda信息取出method、field、class等
        String fieldName = serializedLambda.getImplMethodName().substring("get".length());
        // 从field取出字段名，可以根据实际情况调整
        return toCamelCase(fieldName);

    }
//

    /**
     * @param fn
     * @param <T>
     * @return
     */
    private static <T> Method getMethod(Function<T, ?> fn) {
        // 从function取出序列化方法
        Method writeReplaceMethod;
        try {
            writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
        return writeReplaceMethod;
    }


    private static <T> SerializedLambda getSerializedLambda(Method writeReplaceMethod, Function<T, ?> fn) {
        // 从序列化方法取出序列化的lambda信息
        boolean isAccessible = writeReplaceMethod.isAccessible();
        writeReplaceMethod.setAccessible(true);
        SerializedLambda serializedLambda;
        try {
            serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(fn);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        writeReplaceMethod.setAccessible(isAccessible);
        return serializedLambda;
    }

    /**
     * 驼峰转下划线
     *
     * @param para 字符串
     * @return String
     */
    public static String camelToUnderline(String para) {
        para = lowerFirst(para);
        StringBuilder sb = new StringBuilder(para);
        int temp = 0;
        for (int i = 0; i < para.length(); i++) {
            if (Character.isUpperCase(para.charAt(i))) {
                sb.insert(i + temp, "_");
                temp += 1;
            }
        }
        return sb.toString().toLowerCase();
    }

    /**
     * 将下划线方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。<br>
     * 例如：hello_world=》helloWorld
     *
     * @param str
     * @return
     */
    public static String toCamelCase(String str) {
        if (isEmpty(str)) {
            return str;
        }
        String s = StrUtil.toCamelCase(str);
        return s.substring(0, 1).toLowerCase() + s.substring(1);

    }

    public static String toBigCamelCase(String str) {
        if (isEmpty(str)) {
            return str;
        }
        String s = StrUtil.toCamelCase(str);
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    public static <T> boolean contains(T[] array, T t) {
        if (isEmpty(array)) {
            return false;
        }
        if (isEmpty(t)) {
            return false;
        }
        for (T at : array) {
            if (t.equals(at)) {
                return true;
            }
        }
        return false;
    }

    public static boolean equals(Object obj1, Object obj2) {
        return Objects.equals(obj1, obj2);
    }

    public static long[] toLongArray(String str) {
        String[] strings = str.split(",");
        long[] longs = new long[strings.length];
        for (int i = 0; i < longs.length; i++) {
            longs[i] = Long.parseLong(strings[i]);
        }
        return longs;
    }

    public static long[] toLongArray(List<Long> list) {
        list = list.stream().filter(Objects::nonNull).collect(Collectors.toList());
        long[] longs = new long[list.size()];
        for (int i = 0; i < longs.length; i++) {
            if (list.get(i) != null) {
                longs[i] = list.get(i);
            }
        }
        return longs;
    }

    public static int toInt(byte[] bytes, int start) {
        return (bytes[start] << 8) | bytes[start + 1];
    }


    public static String replaceNonDigitCharacters(String input, String rep) {
        if (isEmpty(input)) {
            return input;
        }
        // 使用正则表达式替换所有除数字和空格以外的字符为逗号
        String replaced = input.replaceAll("[^\\d\\s]", rep);
        return replaced;
    }

    public static String extractNumbers(String input) {
        if (isEmpty(input)) {
            return "";
        }
        // 使用正则表达式匹配数字
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(input);

        StringBuilder result = new StringBuilder();
        while (matcher.find()) {
            // 将匹配到的数字添加到结果字符串
            result.append(matcher.group());
            result.append(" "); // 可以选择添加空格或其他分隔符
        }

        return result.toString().trim(); // 去掉末尾的空格
    }

    public static List<String> toStrList(String str, String s) {
        return StrUtil.split(str, s);
    }

    /**
     * 在前面的list里去掉后边的所有
     *
     * @param src
     * @param rep
     * @return
     */
    public static List<String> replace(List<String> src, List<String> rep) {
        List<String> res = new ArrayList<>();
        for (String s : src) {
            if (!rep.contains(s)) {
                res.add(s);
            }
        }
        return res;
    }

    public static int toMinMax(int i, int min, int max) {
        if (i < min) {
            return min;
        }
        if (i > max) {
            return max;
        }
        return i;
    }

    /**
     * 获取某个元素的List
     *
     * @param list
     * @param propFuc
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<R> getPropList(List<T> list, Function<T, R> propFuc) {
        if (isEmpty(list)) {
            return new ArrayList<>();
        }
        return list.stream().map(propFuc).filter(Objects::nonNull).collect(Collectors.toList());
    }

    public static <T, R> List<String> getPropStrList(List<T> list, Function<T, R> propFuc) {
        return getPropList(list, propFuc).stream().map(Object::toString).collect(Collectors.toList());
    }

    public static <T> List<String> toStrList(List<T> longs) {
        if (isEmpty(longs)) {
            return new ArrayList<>();
        }
        return longs.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.toList());
    }

    public static List<String> toStrList(String str) {
        if (isEmpty(str)) {
            return new ArrayList<>();
        }
        return new ArrayList<>(Arrays.asList(toStrArray(str)));
    }

    /**
     * 取交集
     *
     * @param list1
     * @param list2
     * @param <T>
     * @return
     */
    public static <T> List<T> intersection(List<T> list1, List<T> list2) {
        if (isEmpty(list1)) {
            return list2;
        }
        if (isEmpty(list2)) {
            return list1;
        }
        return list1.stream()
                .filter(list2::contains)
                .collect(Collectors.toList());
    }

    public static <T, E> List<T> mapTo(List<E> list, final ToBack<T, E> callBack) {
        return IntStream.range(0, list.size())
                .mapToObj(index -> {
                    E item = list.get(index);
                    return callBack.back(index, item);
                })
                .collect(Collectors.toList());
    }

    public static <T, R> boolean isEmpty(T t, Function<T, R> func) {
        if (t == null) {
            return true;
        }
        return isEmpty(func.apply(t));
    }

    public static String[] toStrArray(String str) {
        if (isEmpty(str)) {
            return new String[0];
        }
        return str.split(",");
    }

    /**
     * 获取标识符，用于参数清理
     *
     * @param param 参数
     * @return 清理后的标识符
     */
    @Nullable
    public static String cleanIdentifier(@Nullable String param) {
        if (param == null) {
            return null;
        }
        StringBuilder paramBuilder = new StringBuilder();
        for (int i = 0; i < param.length(); i++) {
            char c = param.charAt(i);
            if (Character.isJavaIdentifierPart(c)) {
                paramBuilder.append(c);
            }
        }
        return paramBuilder.toString();
    }


    /**
     * @param list
     * @param function
     * @param <R>
     * @param <T>
     * @return
     */
    public static <R, T> Map<R, T> toMapEntity(List<T> list, Function<T, R> function) {
        return list.stream().collect(Collectors.toMap(function, Function.identity()));
    }

    /**
     * 去重获取某字段list
     *
     * @param list
     * @param sFunction
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<R> getPropDistinctList(List<T> list, Function<T, R> sFunction) {
        return getPropList(list, sFunction).stream().distinct().collect(Collectors.toList());
    }

    public static <T, R> R safeGet(T t, Function<T, R> sFunction) {
        if (t == null) {
            return null;
        }
        return sFunction.apply(t);
    }

    /**
     * 前面为空时返回后面的。
     *
     * @param str1
     * @param str2
     * @return
     */
    public static String toStr(String str1, String str2) {
        return isEmpty(str1) ? str2 : str1;
    }

    public interface ToBack<T, E> {
        T back(int index, E e);
    }
}
